/**
 * GATT服务管理器
 * 处理服务发现、特征值读写、通知等操作
 */

import { bluetoothCore } from '../utils/core.js'
import { bleDeviceManager } from './device-manager.js'
import { 
  createError, 
  createSuccess, 
  formatServiceInfo,
  formatCharacteristicInfo,
  checkRequiredParams,
  withTimeout,
  arrayBuffer2HexString,
  hexString2ArrayBuffer
} from '../utils/utils.js'
import { 
  ERROR_CODES, 
  DEFAULT_CONFIG,
  CHARACTERISTIC_PROPERTIES,
  PLATFORMS
} from '../utils/constants.js'

/**
 * GATT服务管理器类
 */
export class GATTServiceManager {
  constructor() {
    this.platform = bluetoothCore.platform
    this.isH5 = bluetoothCore.isH5
    this.characteristicListeners = new Map()
  }

  /**
   * 获取蓝牙设备所有服务
   */
  async getBLEDeviceServices(options = {}) {
    try {
      checkRequiredParams(options, ['deviceId'])
      
      const { deviceId } = options

      // 检查设备是否已连接
      if (!bleDeviceManager.isDeviceConnected(deviceId)) {
        return createError(ERROR_CODES.NOT_CONNECTED)
      }

      if (this.isH5) {
        return await this._getBLEDeviceServicesH5(options)
      } else {
        return await this._getBLEDeviceServicesNative(options)
      }
    } catch (error) {
      return createError(ERROR_CODES.FAIL, error.message)
    }
  }

  /**
   * H5平台获取设备服务
   */
  async _getBLEDeviceServicesH5(options) {
    const { deviceId } = options
    
    try {
      const deviceInfo = bleDeviceManager.connectedDevices.get(deviceId)
      if (!deviceInfo || !deviceInfo.server) {
        return createError(ERROR_CODES.NOT_CONNECTED, '设备未连接或GATT服务器不可用')
      }

      // 获取设备的授权信息
      const deviceCacheInfo = bluetoothCore.state.devices.get(`${deviceId}_cache_info`)
      const authorizedServices = deviceCacheInfo ? deviceCacheInfo.authorizedServices : new Set()
      
      // 如果有授权的服务列表，优先获取授权的服务
      let services = []
      
      if (authorizedServices.size > 0) {
        // 获取指定的授权服务
        for (const serviceUuid of authorizedServices) {
          try {
            const service = await deviceInfo.server.getPrimaryService(serviceUuid)
            services.push(service)
          } catch (error) {
            console.warn(`[JZ-H5-Bluetooth] Failed to access authorized service ${serviceUuid}:`, error.message)
          }
        }
      } else {
        // 如果没有授权服务列表，尝试获取所有服务（可能失败）
        console.warn('[JZ-H5-Bluetooth] No authorized services found, attempting to get all services')
        try {
          services = await deviceInfo.server.getPrimaryServices()
        } catch (error) {
          return this._handleServiceAccessError(error, deviceId)
        }
      }
      
      const serviceList = services.map(service => {
        const serviceInfo = formatServiceInfo(service, this.platform)
        
        // 缓存服务
        const serviceKey = `${deviceId}-${service.uuid}`
        bluetoothCore.state.services.set(serviceKey, service)
        
        return serviceInfo
      })

      return createSuccess({ services: serviceList })
    } catch (error) {
      console.error('[JZ-H5-Bluetooth] Service discovery error:', error)
      return this._handleServiceDiscoveryError(error, deviceId)
    }
  }

  /**
   * 处理服务访问错误
   */
  _handleServiceAccessError(error, deviceId) {
    console.error('[JZ-H5-Bluetooth] Service access error:', error)
    
    if (error.message && error.message.includes('not allowed to access')) {
      return createError(ERROR_CODES.PERMISSION_DENIED, 
        `服务访问被拒绝：请在选择设备时在 optionalServices 中添加要访问的服务UUID。\n` +
        `当前设备ID: ${deviceId}\n` +
        `解决方案：重新选择设备并在 requestBluetoothDevice 的 optionalServices 参数中声明服务UUID`
      )
    }
    
    return createError(ERROR_CODES.FAIL, `服务访问失败: ${error.message}`)
  }

  /**
   * 处理服务发现错误
   */
  _handleServiceDiscoveryError(error, deviceId) {
    if (error.name === 'NetworkError') {
      return createError(ERROR_CODES.NOT_CONNECTED, '设备连接已断开，请重新连接设备')
    } else if (error.name === 'SecurityError' || (error.message && error.message.includes('not allowed to access'))) {
      return createError(ERROR_CODES.PERMISSION_DENIED,
        `服务发现失败：缺少服务访问权限\n` +
        `错误详情: ${error.message}\n\n` +
        `解决方案：\n` +
        `1. 重新选择设备\n` +
        `2. 在 requestBluetoothDevice 时添加 optionalServices 参数\n` +
        `3. 例如：{ optionalServices: ['battery_service', '00001234-0000-1000-8000-00805f9b34fb'] }`
      )
    } else {
      return createError(ERROR_CODES.FAIL, `服务发现失败: ${error.message}`)
    }
  }

  /**
   * 原生平台获取设备服务
   */
  async _getBLEDeviceServicesNative(options) {
    return new Promise((resolve) => {
      uni.getBLEDeviceServices({
        ...options,
        success: (res) => {
          // 缓存服务信息
          res.services.forEach(service => {
            const serviceKey = `${options.deviceId}-${service.uuid}`
            bluetoothCore.state.services.set(serviceKey, service)
          })
          resolve(createSuccess(res))
        },
        fail: (err) => {
          resolve(createError(err.errCode || ERROR_CODES.FAIL, err.errMsg))
        }
      })
    })
  }

  /**
   * 获取蓝牙设备某个服务中所有特征值
   */
  async getBLEDeviceCharacteristics(options = {}) {
    try {
      checkRequiredParams(options, ['deviceId', 'serviceId'])
      
      const { deviceId, serviceId } = options

      // 检查设备是否已连接
      if (!bleDeviceManager.isDeviceConnected(deviceId)) {
        return createError(ERROR_CODES.NOT_CONNECTED)
      }

      if (this.isH5) {
        return await this._getBLEDeviceCharacteristicsH5(options)
      } else {
        return await this._getBLEDeviceCharacteristicsNative(options)
      }
    } catch (error) {
      return createError(ERROR_CODES.FAIL, error.message)
    }
  }

  /**
   * H5平台获取设备特征值
   */
  async _getBLEDeviceCharacteristicsH5(options) {
    const { deviceId, serviceId } = options
    
    try {
      // 检查服务是否已授权
      const deviceCacheInfo = bluetoothCore.state.devices.get(`${deviceId}_cache_info`)
      const authorizedServices = deviceCacheInfo ? deviceCacheInfo.authorizedServices : new Set()
      
      if (authorizedServices.size > 0 && !authorizedServices.has(serviceId.toLowerCase())) {
        console.warn(`[JZ-H5-Bluetooth] Service ${serviceId} is not authorized`)
        return createError(ERROR_CODES.PERMISSION_DENIED,
          `服务未授权：服务 ${serviceId} 未在设备选择时授权访问\n` +
          `解决方案：重新选择设备并在 optionalServices 中添加此服务UUID`
        )
      }
      
      // 从缓存中获取服务
      const serviceKey = `${deviceId}-${serviceId}`
      const service = bluetoothCore.state.services.get(serviceKey)
      
      if (!service) {
        console.error(`[JZ-H5-Bluetooth] Service ${serviceId} not found in cache`)
        return createError(ERROR_CODES.SERVICE_NOT_FOUND, 
          `服务未找到：请先调用 getBLEDeviceServices 发现服务`)
      }

      // 获取特征值
      const characteristics = await service.getCharacteristics()
      
      const characteristicList = characteristics.map(characteristic => {
        const characteristicInfo = formatCharacteristicInfo(characteristic, this.platform)
        
        // 缓存特征值
        const characteristicKey = `${deviceId}-${serviceId}-${characteristic.uuid}`
        bluetoothCore.state.characteristics.set(characteristicKey, characteristic)
        
        return characteristicInfo
      })

      return createSuccess({ characteristics: characteristicList })
    } catch (error) {
      console.error(`[JZ-H5-Bluetooth] Get characteristics error:`, error)
      
      if (error.name === 'NetworkError') {
        return createError(ERROR_CODES.NOT_CONNECTED, '设备连接已断开，请重新连接设备')
      } else if (error.name === 'NotFoundError') {
        return createError(ERROR_CODES.SERVICE_NOT_FOUND, `服务未找到：${serviceId}`)
      } else if (error.name === 'SecurityError' || (error.message && error.message.includes('not allowed to access'))) {
        return createError(ERROR_CODES.PERMISSION_DENIED,
          `特征值访问被拒绝：服务 ${serviceId} 未授权访问\n` +
          `解决方案：重新选择设备并在 optionalServices 中添加服务UUID`
        )
      } else {
        return createError(ERROR_CODES.FAIL, `获取特征值失败: ${error.message}`)
      }
    }
  }

  /**
   * 原生平台获取设备特征值
   */
  async _getBLEDeviceCharacteristicsNative(options) {
    return new Promise((resolve) => {
      uni.getBLEDeviceCharacteristics({
        ...options,
        success: (res) => {
          // 缓存特征值信息
          res.characteristics.forEach(characteristic => {
            const characteristicKey = `${options.deviceId}-${options.serviceId}-${characteristic.uuid}`
            bluetoothCore.state.characteristics.set(characteristicKey, characteristic)
          })
          resolve(createSuccess(res))
        },
        fail: (err) => {
          resolve(createError(err.errCode || ERROR_CODES.FAIL, err.errMsg))
        }
      })
    })
  }

  /**
   * 读取低功耗蓝牙设备的特征值的二进制数据值
   */
  async readBLECharacteristicValue(options = {}) {
    try {
      checkRequiredParams(options, ['deviceId', 'serviceId', 'characteristicId'])
      
      const { deviceId, serviceId, characteristicId } = options

      // 检查设备是否已连接
      if (!bleDeviceManager.isDeviceConnected(deviceId)) {
        return createError(ERROR_CODES.NOT_CONNECTED)
      }

      if (this.isH5) {
        return await this._readBLECharacteristicValueH5(options)
      } else {
        return await this._readBLECharacteristicValueNative(options)
      }
    } catch (error) {
      return createError(ERROR_CODES.FAIL, error.message)
    }
  }

  /**
   * H5平台读取特征值
   */
  async _readBLECharacteristicValueH5(options) {
    const { deviceId, serviceId, characteristicId } = options
    
    try {
      // 从缓存中获取特征值
      const characteristicKey = `${deviceId}-${serviceId}-${characteristicId}`
      const characteristic = bluetoothCore.state.characteristics.get(characteristicKey)
      
      if (!characteristic) {
        return createError(ERROR_CODES.CHARACTERISTIC_NOT_FOUND)
      }

      // 检查是否支持读取
      if (!characteristic.properties.read) {
        return createError(ERROR_CODES.READ_NOT_PERMIT)
      }

      const value = await withTimeout(
        characteristic.readValue(),
        options.timeout || DEFAULT_CONFIG.READ_TIMEOUT
      )

      return createSuccess({ 
        value: value.buffer,
        hexString: arrayBuffer2HexString(value.buffer)
      })
    } catch (error) {
      if (error.name === 'NetworkError') {
        return createError(ERROR_CODES.NOT_CONNECTED, 'Device disconnected')
      } else if (error.name === 'NotSupportedError') {
        return createError(ERROR_CODES.READ_NOT_PERMIT, 'Read not supported')
      } else {
        return createError(ERROR_CODES.FAIL, error.message)
      }
    }
  }

  /**
   * 原生平台读取特征值
   */
  async _readBLECharacteristicValueNative(options) {
    return new Promise((resolve) => {
      uni.readBLECharacteristicValue({
        ...options,
        success: (res) => resolve(createSuccess(res)),
        fail: (err) => resolve(createError(err.errCode || ERROR_CODES.FAIL, err.errMsg))
      })
    })
  }

  /**
   * 向低功耗蓝牙设备特征值中写入二进制数据
   */
  async writeBLECharacteristicValue(options = {}) {
    try {
      checkRequiredParams(options, ['deviceId', 'serviceId', 'characteristicId', 'value'])
      
      const { deviceId, serviceId, characteristicId } = options

      // 检查设备是否已连接
      if (!bleDeviceManager.isDeviceConnected(deviceId)) {
        return createError(ERROR_CODES.NOT_CONNECTED)
      }

      if (this.isH5) {
        return await this._writeBLECharacteristicValueH5(options)
      } else {
        return await this._writeBLECharacteristicValueNative(options)
      }
    } catch (error) {
      return createError(ERROR_CODES.FAIL, error.message)
    }
  }

  /**
   * H5平台写入特征值
   */
  async _writeBLECharacteristicValueH5(options) {
    const { deviceId, serviceId, characteristicId, value } = options
    
    try {
      // 从缓存中获取特征值
      const characteristicKey = `${deviceId}-${serviceId}-${characteristicId}`
      const characteristic = bluetoothCore.state.characteristics.get(characteristicKey)
      
      if (!characteristic) {
        return createError(ERROR_CODES.CHARACTERISTIC_NOT_FOUND)
      }

      // 检查是否支持写入
      const canWrite = characteristic.properties.write || characteristic.properties.writeWithoutResponse
      if (!canWrite) {
        return createError(ERROR_CODES.WRITE_NOT_PERMIT)
      }

      // 处理不同的数据类型
      let dataBuffer
      if (value instanceof ArrayBuffer) {
        dataBuffer = value
      } else if (typeof value === 'string') {
        dataBuffer = hexString2ArrayBuffer(value)
      } else {
        return createError(ERROR_CODES.FAIL, 'Invalid value type')
      }

      await withTimeout(
        characteristic.writeValue(dataBuffer),
        options.timeout || DEFAULT_CONFIG.WRITE_TIMEOUT
      )

      return createSuccess()
    } catch (error) {
      if (error.name === 'NetworkError') {
        return createError(ERROR_CODES.NOT_CONNECTED, 'Device disconnected')
      } else if (error.name === 'NotSupportedError') {
        return createError(ERROR_CODES.WRITE_NOT_PERMIT, 'Write not supported')
      } else {
        return createError(ERROR_CODES.FAIL, error.message)
      }
    }
  }

  /**
   * 原生平台写入特征值
   */
  async _writeBLECharacteristicValueNative(options) {
    return new Promise((resolve) => {
      uni.writeBLECharacteristicValue({
        ...options,
        success: (res) => resolve(createSuccess(res)),
        fail: (err) => resolve(createError(err.errCode || ERROR_CODES.FAIL, err.errMsg))
      })
    })
  }

  /**
   * 启用低功耗蓝牙设备特征值变化时的notify功能
   */
  async notifyBLECharacteristicValueChange(options = {}) {
    try {
      checkRequiredParams(options, ['deviceId', 'serviceId', 'characteristicId', 'state'])
      
      const { deviceId, serviceId, characteristicId, state } = options

      // 检查设备是否已连接
      if (!bleDeviceManager.isDeviceConnected(deviceId)) {
        return createError(ERROR_CODES.NOT_CONNECTED)
      }

      if (this.isH5) {
        return await this._notifyBLECharacteristicValueChangeH5(options)
      } else {
        return await this._notifyBLECharacteristicValueChangeNative(options)
      }
    } catch (error) {
      return createError(ERROR_CODES.FAIL, error.message)
    }
  }

  /**
   * H5平台启用/禁用通知
   */
  async _notifyBLECharacteristicValueChangeH5(options) {
    const { deviceId, serviceId, characteristicId, state } = options
    
    try {
      // 从缓存中获取特征值
      const characteristicKey = `${deviceId}-${serviceId}-${characteristicId}`
      const characteristic = bluetoothCore.state.characteristics.get(characteristicKey)
      
      if (!characteristic) {
        return createError(ERROR_CODES.CHARACTERISTIC_NOT_FOUND)
      }

      // 检查是否支持通知
      const canNotify = characteristic.properties.notify || characteristic.properties.indicate
      if (!canNotify) {
        return createError(ERROR_CODES.NOTIFY_NOT_PERMIT)
      }

      if (state) {
        // 启用通知
        await characteristic.startNotifications()
        
        // 添加事件监听器
        const listener = (event) => {
          const value = event.target.value
          const data = {
            deviceId,
            serviceId,
            characteristicId,
            value: value.buffer,
            hexString: arrayBuffer2HexString(value.buffer)
          }
          
          // 触发特征值变化事件
          bluetoothCore._triggerCharacteristicValueChange(data)
        }
        
        characteristic.addEventListener('characteristicvaluechanged', listener)
        
        // 缓存监听器以便后续移除
        this.characteristicListeners.set(characteristicKey, listener)
      } else {
        // 禁用通知
        await characteristic.stopNotifications()
        
        // 移除事件监听器
        const listener = this.characteristicListeners.get(characteristicKey)
        if (listener) {
          characteristic.removeEventListener('characteristicvaluechanged', listener)
          this.characteristicListeners.delete(characteristicKey)
        }
      }

      return createSuccess()
    } catch (error) {
      if (error.name === 'NetworkError') {
        return createError(ERROR_CODES.NOT_CONNECTED, 'Device disconnected')
      } else if (error.name === 'NotSupportedError') {
        return createError(ERROR_CODES.NOTIFY_NOT_PERMIT, 'Notifications not supported')
      } else {
        return createError(ERROR_CODES.FAIL, error.message)
      }
    }
  }

  /**
   * 原生平台启用/禁用通知
   */
  async _notifyBLECharacteristicValueChangeNative(options) {
    return new Promise((resolve) => {
      uni.notifyBLECharacteristicValueChange({
        ...options,
        success: (res) => resolve(createSuccess(res)),
        fail: (err) => resolve(createError(err.errCode || ERROR_CODES.FAIL, err.errMsg))
      })
    })
  }

  /**
   * 获取已缓存的服务列表
   */
  getCachedServices(deviceId) {
    const services = []
    for (const [key, service] of bluetoothCore.state.services) {
      if (key.startsWith(deviceId + '-')) {
        services.push(formatServiceInfo(service, this.platform))
      }
    }
    return services
  }

  /**
   * 获取已缓存的特征值列表
   */
  getCachedCharacteristics(deviceId, serviceId) {
    const characteristics = []
    const prefix = `${deviceId}-${serviceId}-`
    
    for (const [key, characteristic] of bluetoothCore.state.characteristics) {
      if (key.startsWith(prefix)) {
        characteristics.push(formatCharacteristicInfo(characteristic, this.platform))
      }
    }
    return characteristics
  }

  /**
   * 清理设备相关的监听器
   */
  clearDeviceListeners(deviceId) {
    const keysToDelete = []
    for (const key of this.characteristicListeners.keys()) {
      if (key.startsWith(deviceId + '-')) {
        keysToDelete.push(key)
      }
    }
    
    keysToDelete.forEach(key => {
      this.characteristicListeners.delete(key)
    })
  }

  /**
   * 重置服务管理器
   */
  reset() {
    this.characteristicListeners.clear()
  }
}

// 导出单例实例
export const gattServiceManager = new GATTServiceManager() 